#ifdef Q_OS_LINUX
#include <unistd.h>
#endif
#include "../common/xmldocument.h"
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include <QTextCodec>
#else
#include <QStringConverter>
#endif
//#include "../common/QtCrypto.h"
//
///************************************************************************/
////自定义xml类 -- 构造函数
////输入参数：
////      file -- 文件名
////      mode -- 读写权限
////      root -- 根节点名（用于写）
////      pchCodecName -- 编码名（默认UTF-16）
////      parent -- 父Object
////返回参数：
////      根节点
///************************************************************************/
//XMLDocument::XMLDocument( const QString &file,
//                          QIODevice::OpenMode mode,
//                          bool bDecrypt,
//                          const QString &root,
//                          const char* pchCodecName,
//                          QObject *parent )
//    :QObject(parent)
//{
//    m_strFile = file;
//    m_strRootName = root;
//    m_mode = mode;
//    m_strCodecName = pchCodecName;
//
//    QByteArray baPreCryptoData;
//    QByteArray baCryptoData;
//    m_file.setFileName(m_strFile);
//    m_bValid = m_file.open(mode);
//    if( m_bValid )
//    {
//        baPreCryptoData = m_file.readAll();
//
//        if(bDecrypt)
//        {
//            if(baPreCryptoData.count() != 0)
//            {
////                baCryptoData = deCrypt(baPreCryptoData);
//            }
//        }
//        else
//        {
//            baCryptoData = baPreCryptoData;
//        }
//
//         baCryptoData = baPreCryptoData;
//
//        QString strErr;
//        int iErrLine;
//        int iErrColumn;
//        if( !m_doc.setContent(baCryptoData,&strErr,&iErrLine,&iErrColumn) )
//        {
//            QString strHead = QString("version=\"1.0\" encoding=\"%1\"").arg(m_strCodecName);
//            QDomProcessingInstruction instruction = m_doc.createProcessingInstruction("xml",strHead);
//            m_doc.appendChild(instruction);
//            m_element = m_doc.createElement(m_strRootName);
//            m_doc.appendChild(m_element);
//        }
//        else
//        {
//            m_element = m_doc.documentElement();
//            m_element.setTagName(m_strRootName);
//        }
//    }
//    else
//    {
//        qWarning("XMLDocument::XMLDocument:open xml file failed\n");
//    }
//}

namespace DataSpecificationGW
{
    /************************************************************************/
    //自定义xml类 -- 构造函数
    //输入参数：
    //      root -- XML格式数据，或者根节点名（用于写）
    //      pchCodecName -- 编码名（默认UTF-16）
    //      parent -- 父Object
    //返回参数：
    //      根节点
    /************************************************************************/
    XMLDocument::XMLDocument(const QString& root,
        const char* pchCodecName,
        QObject* parent)
        :QObject(parent),
        m_strCodecName(pchCodecName)
    {
        if (!m_doc.setContent(root))
        {
            QString strHead = QString("version=\"1.0\" encoding=\"%1\"").arg(pchCodecName);
            QDomProcessingInstruction instruction = m_doc.createProcessingInstruction("xml", strHead);
            m_doc.appendChild(instruction);

            m_strRootName = root;

            m_element = m_doc.createElement(m_strRootName);
            m_doc.appendChild(m_element);
        }
        else
        {
            m_element = m_doc.documentElement();
        }
    }

    /************************************************************************/
    //自定义xml类 -- 析构函数
    //存储
    /************************************************************************/
    XMLDocument::~XMLDocument()
    {
        //    if( m_mode & QIODevice::WriteOnly )
        //        save();
    }

    /************************************************************************/
    //自定义xml类 -- 清除
    /************************************************************************/
    void XMLDocument::clear()
    {
        m_doc.clear();
        m_element = m_doc.createElement(m_strRootName);
        m_doc.appendChild(m_element);
    }

    /************************************************************************/
    //自定义xml类 -- 子节点
    //输入参数：
    //      name -- 节点名
    //返回参数：
    //      元素列表
    /************************************************************************/
    QList<QDomElement> XMLDocument::childElement(const QString &name) const
    {
        QDomNodeList nodesread;
        QList<QDomElement> elements;
        nodesread = m_element.childNodes();
        for (int i = 0; i < nodesread.count(); i++)
        {
            QDomNode node = nodesread.at(i);
            if (node.isElement())
            {
                if (name.isNull() || (node.nodeName() == name))
                {
                    elements << node.toElement();
                }
            }
        }
        return elements;
    }

    /************************************************************************/
    //自定义xml类 -- 开始一个节点
    //输入参数：
    //      name -- 节点名
    /************************************************************************/
    void XMLDocument::beginElement(const QString& name)
    {
        QDomElement element = m_element.firstChildElement(name);
        if (element.isNull())
        {
            element = m_doc.createElement(name);
            m_element.appendChild(element);
        }
        m_element = element;
    }


    /************************************************************************/
    //自定义xml类 -- 添加一个节点
    //输入参数：
    //      name -- 节点名
    //返回参数：
    //      节点
    /************************************************************************/
    QDomElement XMLDocument::addElement(const QString &name)
    {
        QDomElement element = m_doc.createElement(name);
        m_element.appendChild(element);

        return element;
    }

    /************************************************************************/
    //自定义xml类 -- 结束一个节点
    /************************************************************************/
    void XMLDocument::endElement()
    {
        if (!m_element.isNull())
        {
            m_element = m_element.parentNode().toElement();
        }
    }

    /************************************************************************/
    //自定义xml类 -- 删除节点
    //输入参数：
    //      name -- 节点名
    /************************************************************************/
    void XMLDocument::removeElement(const QString& name)
    {
        QDomNodeList nodes = m_element.childNodes();
        for (int i = 0; i < nodes.count(); i++)
        {
            QDomNode node = nodes.at(i);
            if (node.nodeName() == name)
            {
                m_element.removeChild(node);
            }
        }
    }
    /************************************************************************/
    //自定义xml类 -- 是否存在节点
    //输入参数：
    //      name -- 节点名
    /************************************************************************/
    bool XMLDocument::hasElement(const QString &name) const
    {
        QDomNodeList nodes = m_element.childNodes();
        for (int i = 0; i < nodes.count(); i++)
        {
            QDomNode node = nodes.at(i);
            if (node.nodeName() == name)
            {
                return true;
            }
        }
        return false;
    }
    /************************************************************************/
    //自定义xml类 -- 键值操作
    //输入参数：
    //      key -- 键
    //      value -- 值
    /************************************************************************/
    void XMLDocument::setValue(const QString& key, const QString& value)
    {
        removeElement(key);
        beginElement(key);
        setText(value);
        endElement();
    }

    /************************************************************************/
    //自定义xml类 -- 键值操作
    //输入参数：
    //      key -- 键
    //      defValue -- 默认值
    //返回参数：
    //      值
    /************************************************************************/
    QString XMLDocument::value(const QString& key, const QString& defValue) const
    {
        QString text;
        QDomElement element = m_element.firstChildElement(key);
        if (element.isNull())
        {
            return defValue;
        }
        return element.text();
    }

#if 1
    /************************************************************************/
    //自定义xml类 -- 获取文档字节流
    //返回参数：
    //      文档字节流
    /************************************************************************/
    QByteArray XMLDocument::getByteArray() const
    {
        QByteArray dataIn = m_doc.toByteArray(2);
        QTextStream in(&dataIn);

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
        QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
        in.setCodec("UTF-8");
#else
        in.setEncoding(QStringConverter::Utf8);
#endif

        QByteArray dataOut;
        QTextStream out(&dataOut);

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
        out.setCodec(m_strCodecName.toLatin1().constData());
#else
        out.setEncoding(QStringConverter::encodingForName(m_strCodecName.toLatin1().constData()).value_or(QStringConverter::Utf8));
#endif

        out << in.readAll();
        out.flush();

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
        QTextCodec::setCodecForLocale(QTextCodec::codecForName("GBK"));
#endif

        return dataOut;
    }
#else

    QByteArray XMLDocument::getByteArray() const //new method defined by zhou dingyu in TB
    {
        QString str;
        QTextStream in(&str);  //QTextStream使用Local设置
        in.setCodec(QTextCodec::codecForName("UTF-8"));  //防止Local不是UTF-8
        QByteArray dataIn = m_doc.toByteArray(2);
        in << dataIn;
        in.flush();

        QByteArray dataOut;
        QTextStream out(&dataOut);
        out.setCodec(m_strCodecName.toLatin1().constData());

        out << str;
        out.flush();

        return dataOut;
    }
#endif
    /************************************************************************/
    //自定义xml类 -- 设置文本
    //输入参数：
    //      text -- 文本
    /************************************************************************/
    void XMLDocument::setText(const QString &text)
    {
        QDomNodeList nodes = m_element.childNodes();
        for (int i = 0; i < nodes.count(); i++)
        {
            QDomNode node = nodes.at(i);
            if (node.isText())
            {
                m_element.removeChild(node);
            }
        }
        //写入value
        QDomText textNode = m_doc.createTextNode(text);
        m_element.appendChild(textNode);
    }

    /************************************************************************/
    //自定义xml类 -- 文本
    //返回参数：
    //      文本
    /************************************************************************/
    QString XMLDocument::text() const
    {
        return m_element.text();
    }

    /************************************************************************/
    //自定义xml类 -- 判断是否存在文本
    /************************************************************************/
    bool XMLDocument::hasText()
    {
        return (!m_element.text().isNull());
    }

    /************************************************************************/
    //自定义xml类 -- 设置属性
    //输入参数：
    //      name -- 属性名
    //      attribute -- 属性值
    /************************************************************************/
    void XMLDocument::setAttribute(const QString &name, const QString &attribute)
    {
        if (m_element.hasAttribute(name))
        {
            m_element.removeAttribute(name);
        }
        m_element.setAttribute(name, attribute);
    }

    /************************************************************************/
    //自定义xml类 -- 删除属性
    //输入参数：
    //      name -- 属性名
    /************************************************************************/
    void XMLDocument::removeAttribute(const QString &name)
    {
        m_element.removeAttribute(name);
    }

    /************************************************************************/
    //自定义xml类 -- 是否存在属性
    //输入参数：
    //      name -- 属性名
    /************************************************************************/
    bool XMLDocument::hasAttribute(const QString &name)
    {
        return m_element.hasAttribute(name);
    }

    /************************************************************************/
    //自定义xml类 -- 是否存在属性
    /************************************************************************/
    bool XMLDocument::hasAttributes()
    {
        return m_element.hasAttributes();
    }
    /************************************************************************/
    //自定义xml类 -- 获取属性
    //输入参数：
    //      name -- 属性名
    //      defAttribute -- 默认属性值
    /************************************************************************/
    QString XMLDocument::attribute(const QString& name, const QString& defAttribute) const
    {
        return m_element.attribute(name, defAttribute);
    }

    /************************************************************************/
    //自定义xml类 -- 获取属性
    /************************************************************************/
    QXmlStreamAttributes XMLDocument::attributes() const
    {
        QDomNamedNodeMap nodes = m_element.attributes();
        QXmlStreamAttributes maps;
        for (int i = 0; i < nodes.count(); i++)
        {
            QDomNode node = nodes.item(i);
            maps.append(node.toAttr().name(), node.toAttr().value());
        }
        return maps;
    }

    ///************************************************************************/
    ////自定义xml类 -- 存储
    ///************************************************************************/
    //bool XMLDocument::save(bool bCrypt)
    //{
    //    bool isSuccess = false;
    //    //写入文件
    //    if(m_file.exists())
    //    {
    //        m_file.resize(0);
    //        if(bCrypt)
    //        {
    //            QByteArray data = /*enCrypt( */getByteArray() /*)*/;
    //            m_file.write( data );
    //        }
    //        else
    //        {
    //            m_file.write( getByteArray() );
    //        }
    //        isSuccess = m_file.flush();
    //#ifdef Q_OS_LINUX
    //        if(isSuccess == true)
    //        {
    //            //立刻把文件同步到磁盘
    //            //sync();
    //        }
    //#endif
    //    }
    //
    //    return isSuccess;
    //}
}
